/*
 * Copyright (c) 2009. Silenus Consultoria, S.L.
 */
package es.silenus.detecta.olap;

import mondrian.olap.Member;
import mondrian.olap.MemberFormatter;
import mondrian.olap.Property;

import java.text.DecimalFormat;
import java.text.Format;
import java.text.SimpleDateFormat;

import java.util.HashMap;
import java.util.Map;


/**
 * A name formatter when name is not a string.
 *
 * @author <a href="mailto:malonso@silenus-consultoria.es">Mariano Alonso</a>
 *
 * @since 16-abr-2009 10:31:40
 */
public class NameFormatter implements MemberFormatter {
	/**
	 * Formatters are not thread-safe, so wrap them into a thread-local variable.
	 */
	private static final ThreadLocal<Map<Class, Format>> FORMATTERS = new ThreadLocal<Map<Class, Format>>() {
			/**
			 * Returns the current thread's "initial value" for this thread-local variable.  This method will be
			 * invoked the first time a thread accesses the variable with the {@link #get} method, unless the thread
			 * previously invoked the {@link #set} method, in which case the <tt>initialValue</tt> method will not be
			 * invoked for the thread.  Normally, this method is invoked at most once per thread, but it may be invoked
			 * again in case of subsequent invocations of {@link #remove} followed by {@link #get}.<p>This
			 * implementation simply returns <tt>null</tt>; if the programmer desires thread-local variables to have an
			 * initial value other than <tt>null</tt>, <tt>ThreadLocal</tt> must be subclassed, and this method overridden.
			 * Typically, an anonymous inner class will be used.</p>
			 *
			 * @return the initial value for this thread-local
			 */
			protected Map<Class, Format> initialValue() {
				HashMap<Class, Format> formatters = new HashMap<Class, Format>();

				SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");

				formatters.put(java.util.Date.class, dateFormat);
				formatters.put(java.sql.Date.class, dateFormat);
				formatters.put(java.sql.Timestamp.class, dateFormat);

				DecimalFormat smallNumberFormat = new DecimalFormat("###,##0.##");

				formatters.put(Integer.class, smallNumberFormat);
				formatters.put(Short.class, smallNumberFormat);
				formatters.put(Long.class, smallNumberFormat);
				formatters.put(Byte.class, smallNumberFormat);

				DecimalFormat bigNumberFormat = new DecimalFormat("###,###,###,##0.##");

				formatters.put(Float.class, bigNumberFormat);
				formatters.put(Double.class, bigNumberFormat);
				formatters.put(java.math.BigDecimal.class, bigNumberFormat);

				return formatters;
			}
		};

/**
   * Constructor.
   */
	public NameFormatter() {
	}

	/**
	 * Retrieves the appropiate formatter for a given class.
	 *
	 * @param theClass the class.
	 *
	 * @return the format.
	 */
	protected Format getFormatter(final Class theClass) {
		return FORMATTERS.get().get(theClass);
	}

	/**
	 * Returns the string to be displayed as a caption for a given member.
	 *
	 * @param member the member.
	 *
	 * @return the caption.
	 */
	public String formatMember(final Member member) {
		Object name = member.getPropertyValue(Property.NAME.name);
		Class nameClass = name.getClass();
		Format theFormat = getFormatter(nameClass);

		if(theFormat != null) {
			return theFormat.format(name);
		}

		return name.toString();
	}
}
